import { createClient, RedisClientType } from "redis";
import { GenericContainer, StartedTestContainer, Wait } from "testcontainers"; // 可选导入 Wait
import { describe, expect, beforeAll, afterAll, test, jest } from '@jest/globals'; // 明确导入 jest

describe("Redis Integration Test", () => {
  jest.setTimeout(120000);

  let container: StartedTestContainer | undefined; 
  let redisClient: RedisClientType<any, any, any> | undefined; 

  beforeAll(async () => {
    console.log("Starting Redis container (using redis:alpine)...");
    try {
      container = await new GenericContainer("redis:alpine")
        .withExposedPorts(6379)
        .start();
      console.log(`Redis container started on ${container.getHost()}:${container.getMappedPort(6379)}`);

      const redisUrl = `redis://${container.getHost()}:${container.getMappedPort(6379)}`;
      console.log(`Connecting Redis client to ${redisUrl}...`);
      redisClient = createClient({
        url: redisUrl
      });

      redisClient.on('error', (err) => console.error('Redis Client Error:', err));

      await redisClient.connect();
      console.log("Redis client connected.");

    } catch (error) {
      console.error("Error during beforeAll setup:", error);
      throw error;
    }
  }, 180000); 

  afterAll(async () => {
    console.log("Cleaning up resources...");
    if (redisClient && redisClient.isOpen) { 
      try {
        console.log("Disconnecting Redis client...");
        await redisClient.disconnect();
        console.log("Redis client disconnected.");
      } catch (error) {
        console.error("Error disconnecting Redis client:", error);
      }
    } else if (redisClient) {
        console.log("Redis client exists but is not open.");
    } else {
        console.log("Redis client was not initialized.");
    }

    if (container) { 
      try {
        console.log("Stopping Redis container...");
        await container.stop();
        console.log("Redis container stopped.");
      } catch (error) {
        console.error("Error stopping Redis container:", error);
      }
    } else {
      console.log("Redis container was not started.");
    }
    console.log("Cleanup finished.");
  });

  test("should set and get a value from Redis", async () => {
    if (!redisClient) {
        throw new Error("Redis client is not available for the test.");
    }

    const key = "mykey";
    const value = "myvalue";

    console.log(`Setting key "${key}" to value "${value}"...`);
    await redisClient.set(key, value);
    console.log("Key set.");

    console.log(`Getting value for key "${key}"...`);
    const retrievedValue = await redisClient.get(key);
    console.log(`Retrieved value: "${retrievedValue}"`);

    expect(retrievedValue).toBe(value);
  });

  test("should handle non-existent key", async () => {
    if (!redisClient) {
      throw new Error("Redis client is not available for the test.");
    }
    const key = "nonexistentkey";
    console.log(`Getting value for non-existent key "${key}"...`);
    const retrievedValue = await redisClient.get(key);
    console.log(`Retrieved value: ${retrievedValue}`);
    expect(retrievedValue).toBeNull();
  });
});

